home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / Santa Paravia / paravia.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  28.3 KB  |  1,082 lines

  1. /******************************************************************************
  2.  **                                                                          **
  3.  ** Santa Paravia & Fiumaccio. Translated from the original TRS-80 BASIC     **
  4.  ** source code into C by Thomas Knox <tom@vushta.com>.                      **
  5.  **                                                                          **
  6.  ** Original program (C) 1979 by George Blank                                **
  7.  **     <gwblank@postoffice.worldnet.att.net>                                **
  8.  **                                                                          **
  9.  ******************************************************************************/
  10.  
  11. /*
  12. Copyright (C) 2000 Thomas Knox
  13. Portions Copyright (C) 1979 by George Blank, used with permission.
  14.  
  15. This program is free software; you can redistribute it and/or
  16. modify it under the terms of the GNU General Public License  
  17. as published by the Free Software Foundation; either version 2
  18. of the License, or (at your option) any later version.
  19.  
  20. This program is distributed in the hope that it will be useful,
  21. but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  23. GNU General Public License for more details.
  24.  
  25. You should have received a copy of the GNU General Public License
  26. along with this program; if not, write to the Free Software
  27. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  28.  
  29. Thomas Knox
  30. 2809 Gabriel Ave.
  31. Zion, IL 60099
  32. tom@vushta.com
  33. */
  34.  
  35. /* Declare our standard C headers. */ 
  36. #include <stdio.h>
  37. #include <string.h>
  38. #include <time.h>
  39. #include <stdlib.h>
  40. #include <curses.h>
  41.  
  42. /* Declare an enum to emulate a Boolean. */
  43. enum TrueFalse {True, False};
  44. typedef enum TrueFalse boolean;
  45.  
  46. /* Declare our player definition. */
  47. struct Player
  48. {
  49.     int Cathedral, Clergy, CustomsDuty, CustomsDutyRevenue, DeadSerfs;
  50.     int Difficulty, FleeingSerfs, GrainDemand, GrainPrice, GrainReserve;
  51.     int Harvest, IncomeTax, IncomeTaxRevenue, RatsAte;
  52.     int Justice, JusticeRevenue, Land, Marketplaces, MarketRevenue;
  53.     int Merchants, MillRevenue, Mills, NewSerfs, Nobles, OldTitle, Palace;
  54.     int Rats, SalesTax, SalesTaxRevenue, Serfs, SoldierPay, Soldiers, TitleNum;
  55.     int TransplantedSerfs, Treasury, WhichPlayer, Year, YearOfDeath;
  56.     char City[15], Name[25], Title[15];
  57.     float PublicWorks, LandPrice;
  58.     boolean InvadeMe, IsBankrupt, IsDead, IWon, MaleOrFemale, NewTitle;
  59. } Player;
  60. typedef struct Player player;
  61.  
  62. /* Declare our list of cities. */
  63. char CityList[7][15] = {"Santa Paravia", "Fiumaccio", "Torricella", "Molinetto",
  64.                         "Fontanile", "Romanga", "Monterana"};
  65.  
  66. /* Declare our male titles. */
  67. char MaleTitles[8][15] = {"Sir", "Baron", "Count", "Marquis", "Duke",
  68.                           "Grand Duke", "Prince", "* H.R.H. King"};
  69.  
  70. /* Declare our female titles. */
  71. char FemaleTitles[8][15] = {"Lady", "Baroness", "Countess", "Marquise",
  72.                             "Duchess", "Grand Duchess", "Princess",
  73.                 "* H.R.H. Queen"};
  74.  
  75. /* Our prototypes. */
  76. int main(void);
  77. int Random(int);
  78. void InitializePlayer(player*, int, int, int, char*, boolean);
  79. void AddRevenue(player *);
  80. int AttackNeighbor(player *, player *);
  81. void BuyCathedral(player *);
  82. void BuyGrain(player *);
  83. void BuyLand(player *);
  84. void BuyMarket(player *);
  85. void BuyMill(player *);
  86. void BuyPalace(player *);
  87. void BuySoldiers(player *);
  88. int limit10(int, int);
  89. boolean CheckNewTitle(player *);
  90. void GenerateHarvest(player *);
  91. void GenerateIncome(player *);
  92. void ChangeTitle(player *);
  93. void NewLandAndGrainPrices(player *);
  94. void PrintGrain(player *);
  95. int ReleaseGrain(player *);
  96. void SeizeAssets(player *);
  97. void SellGrain(player *);
  98. void SellLand(player *);
  99. void SerfsDecomposing(player *, float);
  100. void SerfsProcreating(player *, float);
  101. void PrintInstructions(void);
  102. void PlayGame(player [], int);
  103. void NewTurn(player *, int, player [], player *);
  104. void BuySellGrain(player *);
  105. void AdjustTax(player *);
  106. void DrawMap(player *);
  107. void StatePurchases(player *, int, player []);
  108. void ShowStats(player [], int);
  109. void ImDead(player *);
  110.  
  111. int main(void)
  112. {
  113.     player MyPlayers[6];
  114.     int NumOfPlayers, i, level;
  115.     char string[255], name[25];
  116.     boolean MorF;
  117.     
  118.     /* Initialize the random number generator seed. */
  119.     srand(time(NULL));
  120.  
  121.     /* Start the game. */
  122.     printf("Santa Paravia and Fiumaccio\n");
  123.     printf("\nDo you wish instructions (Y or N)? ");
  124.     fgets(string, 254, stdin);
  125.     if(string[0] == 'y' || string[0] == 'Y')
  126.         PrintInstructions();
  127.  
  128.     printf("How many people want to play (1 to 6)? ");
  129.     fgets(string, 254, stdin);
  130.     NumOfPlayers = (int)atoi(string);
  131.     if(NumOfPlayers < 1 || NumOfPlayers > 6)
  132.     {
  133.         printf("Thanks for playing.\n");
  134.         return(0);
  135.     }
  136.     
  137.     printf("What will be the difficulty of this game:\n1. Apprentice\n");
  138.     printf("2. Journeyman\n3. Master\n4. Grand Master\n\nChoose: ");
  139.     fgets(string, 254, stdin);
  140.     level = (int)atoi(string);
  141.     if(level < 1)
  142.         level = 1;
  143.     if(level > 4)
  144.         level = 4;
  145.     
  146.     for(i = 0; i < NumOfPlayers; i++)
  147.     {
  148.         printf("Who is the ruler of %s? ", CityList[i]);
  149.         fgets(name, 24, stdin);
  150.     /* Strip off the trailing \n. */
  151.     name[strlen(name) - 1] = '\0';
  152.         printf("Is %s a man or a woman (M or F)? ", name);
  153.         fgets(string, 3, stdin);
  154.         if(string[0] == 'm' || string[0] == 'M')
  155.             MorF = True;
  156.         else
  157.             MorF = False;
  158.         
  159.         InitializePlayer(&MyPlayers[i], 1400, i, level, name, MorF);
  160.     }
  161.  
  162.     /* Enter the main game loop. */
  163.     PlayGame(MyPlayers, NumOfPlayers);
  164.  
  165.     /* We're finished. */
  166.     return(0);
  167. }
  168.  
  169. /******************************************************************************
  170.  ** This function will take a parameter Hi and return a random integer       **
  171.  ** between 0 and Hi.                                                        **
  172.  ******************************************************************************/
  173. int Random(int Hi)
  174. {
  175.     float RanNum;
  176.  
  177.     RanNum = (float)rand();
  178.     RanNum /= (float)RAND_MAX;
  179.     RanNum *= (float)Hi;
  180.     return((int)RanNum);
  181. }
  182.  
  183. void InitializePlayer(player *Me, int year, int city, int level, char *name,
  184.                   boolean MorF)
  185. {
  186.     /* This is pretty straightforward. */
  187.     Me->Cathedral = 0;
  188.     strcpy(Me->City, CityList[city]);
  189.     Me->Clergy = 5;
  190.     Me->CustomsDuty = 25;
  191.     Me->Difficulty = level;
  192.     Me->GrainPrice = 25;
  193.     Me->GrainReserve = 5000;
  194.     Me->IncomeTax = 5;
  195.     Me->IsBankrupt = False;
  196.     Me->IsDead = False;
  197.     Me->IWon = False;
  198.     Me->Justice = 2;
  199.     Me->Land = 10000;
  200.     Me->LandPrice = 10.0;
  201.     Me->MaleOrFemale = MorF;
  202.     Me->Marketplaces = 0;
  203.     Me->Merchants = 25;
  204.     Me->Mills = 0;
  205.     strcpy(Me->Name, name);
  206.     Me->Nobles = 4;
  207.     Me->OldTitle = 1;
  208.     Me->Palace = 0;
  209.     Me->PublicWorks = 1.0;
  210.     Me->SalesTax = 10;
  211.     Me->Serfs = 2000;
  212.     Me->Soldiers = 25;
  213.     Me->TitleNum = 1;
  214.     if(Me->MaleOrFemale == True)
  215.         strcpy(Me->Title, MaleTitles[0]);
  216.     else
  217.         strcpy(Me->Title, FemaleTitles[0]);
  218.     if(city == 6) strcpy(Me->Title, "Baron");
  219.     Me->Treasury = 1000;
  220.     Me->WhichPlayer = city;
  221.     Me->Year = year;
  222.     Me->YearOfDeath = year + 20 + Random(35);
  223.  
  224.     return;
  225. }
  226.  
  227. void AddRevenue(player *Me)
  228. {
  229.     Me->Treasury += (Me->JusticeRevenue + Me->CustomsDutyRevenue);
  230.     Me->Treasury += (Me->IncomeTaxRevenue + Me->SalesTaxRevenue);
  231.     
  232.     /* Penalize deficit spending. */
  233.     if(Me->Treasury < 0)
  234.         Me->Treasury = (int)((float)Me->Treasury * 1.5);
  235.     
  236.     /* Will a title make the creditors happy (for now)? */
  237.     if(Me->Treasury < (-10000 * Me->TitleNum))
  238.         Me->IsBankrupt = True;
  239.     
  240.     return;
  241. }
  242.  
  243. int AttackNeighbor(player *Me, player *Him)
  244. {
  245.     int LandTaken;
  246.     int deadsoldiers = 0;
  247.     
  248.     if(Me->WhichPlayer == 7)
  249.         LandTaken = Random(9000) + 1000;
  250.     else
  251.         LandTaken = (Me->Soldiers * 1000) - (Me->Land / 3);
  252.  
  253.     if(LandTaken > (Him->Land - 5000))
  254.             LandTaken = (Him->Land - 5000) / 2;
  255.     
  256.     Me->Land += LandTaken;
  257.     Him->Land -= LandTaken;
  258.     
  259.     printf("\a\n%s %s of %s invades and seizes %d hectares of land!\n",
  260.             Me->Title, Me->Name, Me->City, LandTaken);
  261.  
  262.     deadsoldiers = Random(40);
  263.     if(deadsoldiers > (Him->Soldiers - 15))
  264.         deadsoldiers = Him->Soldiers - 15;
  265.  
  266.     Him->Soldiers -= deadsoldiers;
  267.     printf("%s %s loses %d soldiers in battle.\n", Him->Title, Him->Name,
  268.             deadsoldiers);
  269.  
  270.     return(LandTaken);
  271. }
  272.  
  273. void BuyCathedral(player *Me)
  274. {
  275.     Me->Cathedral += 1;
  276.     Me->Clergy += Random(6);
  277.     Me->Treasury -= 5000;
  278.     Me->PublicWorks += 1.0;
  279.     
  280.     return;
  281. }
  282.  
  283. void BuyGrain(player *Me)
  284. {
  285.     char string[256];
  286.     int HowMuch;
  287.  
  288.     printf("How much grain do you want to buy (0 to specify a total)? ");
  289.     fgets(string, 255, stdin);
  290.     HowMuch = (int)atoi(string);
  291.     if(HowMuch == 0)
  292.     {
  293.         printf("How much total grain do you wish? ");
  294.         fgets(string, 255, stdin);
  295.         HowMuch = (int)atoi(string);
  296.         HowMuch -= Me->GrainReserve;
  297.         if(HowMuch < 0)
  298.         {
  299.             printf("Invalid total amount.\n\n");
  300.             return;
  301.         }
  302.     }
  303.  
  304.     Me->Treasury -= (HowMuch * Me->GrainPrice / 1000);
  305.     Me->GrainReserve += HowMuch;
  306.     
  307.     return;
  308. }
  309.  
  310. void BuyLand(player *Me)
  311. {
  312.     char string[256];
  313.     int HowMuch;
  314.  
  315.     printf("How much land do you want to buy? ");
  316.     fgets(string, 255, stdin);
  317.     HowMuch = (int)atoi(string);
  318.  
  319.     Me->Land += HowMuch;
  320.     Me->Treasury -= (int)(((float)HowMuch * Me->LandPrice));
  321.     
  322.     return;
  323. }
  324.  
  325. void BuyMarket(player *Me)
  326. {
  327.     Me->Marketplaces += 1;
  328.     Me->Merchants += 5;
  329.     Me->Treasury -= 1000;
  330.     Me->PublicWorks += 1.0;
  331.     
  332.     return;
  333. }
  334.  
  335. void BuyMill(player *Me)
  336. {
  337.     Me->Mills += 1;
  338.     Me->Treasury -= 2000;
  339.     Me->PublicWorks += 0.25;
  340.     
  341.     return;
  342. }
  343.  
  344. void BuyPalace(player *Me)
  345. {
  346.     Me->Palace += 1;
  347.     Me->Nobles += Random(2);
  348.     Me->Treasury -= 3000;
  349.     Me->PublicWorks += 0.5;
  350.     
  351.     return;
  352. }
  353.  
  354. void BuySoldiers(player *Me)
  355. {
  356.     Me->Soldiers += 20;
  357.     Me->Serfs -= 20;
  358.     Me->Treasury -= 500;
  359. }
  360.  
  361. int limit10(int num, int denom)
  362. {
  363.     register int val;
  364.     
  365.     val = num / denom;
  366.     return(val > 10 ? 10 : val);
  367. }
  368.  
  369. boolean CheckNewTitle(player *Me)
  370. {
  371.     int Total;
  372.     
  373.     /* Tally up our success so far . . . . */
  374.     Total  = limit10(Me->Marketplaces, 1);
  375.     Total += limit10(Me->Palace, 1);
  376.     Total += limit10(Me->Cathedral, 1);
  377.     Total += limit10(Me->Mills, 1);
  378.     Total += limit10(Me->Treasury, 5000);
  379.     Total += limit10(Me->Land, 6000);
  380.     Total += limit10(Me->Merchants, 50);
  381.     Total += limit10(Me->Nobles, 5);
  382.     Total += limit10(Me->Soldiers, 50);
  383.     Total += limit10(Me->Clergy, 10);
  384.     Total += limit10(Me->Serfs, 2000);
  385.     Total += limit10((int)(Me->PublicWorks * 100.0), 500);
  386.     
  387.     Me->TitleNum = (Total / Me->Difficulty) - Me->Justice;
  388.     if(Me->TitleNum > 7)
  389.         Me->TitleNum = 7;
  390.     if(Me->TitleNum < 0)
  391.         Me->TitleNum = 0;
  392.     
  393.     /* Did we change (could be backwards or forwards)? */
  394.     if(Me->TitleNum > Me->OldTitle)
  395.     {
  396.         Me->OldTitle = Me->TitleNum;
  397.         ChangeTitle(Me);
  398.     printf("\aGood news! %s has achieved the rank of %s\n\n", Me->Name,
  399.             Me->Title);
  400.         
  401.         return(True);
  402.     }
  403.     
  404.     Me->TitleNum = Me->OldTitle;
  405.     return(False);
  406. }
  407.  
  408. void GenerateHarvest(player *Me)
  409. {
  410.     Me->Harvest = (Random(5) + Random(6)) / 2;
  411.     Me->Rats = Random(50);
  412.     Me->GrainReserve = ((Me->GrainReserve * 100) -
  413.                 (Me->GrainReserve * Me->Rats)) / 100;
  414.     
  415.     return;
  416. }
  417.  
  418. void GenerateIncome(player *Me)
  419. {
  420.     float y;
  421.     int revenues = 0;
  422.     char string[256];
  423.     
  424.     Me->JusticeRevenue = (Me->Justice * 300 - 500) * Me->TitleNum;
  425.     switch(Me->Justice)
  426.     {
  427.     case 1: strcpy(string, "Very Fair"); break;
  428.     case 2: strcpy(string, "Moderate"); break;
  429.     case 3: strcpy(string, "Harsh"); break;
  430.     case 4: strcpy(string, "Outrageous");
  431.     }
  432.  
  433.     y = 150.0 - (float)Me->SalesTax - (float)Me->CustomsDuty -
  434.             (float)Me->IncomeTax;
  435.     if(y < 1.0)
  436.         y = 1.0;
  437.     
  438.     y /= 100.0;
  439.     
  440.     Me->CustomsDutyRevenue = Me->Nobles * 180 + Me->Clergy * 75 +
  441.                          Me->Merchants * 20 * y;
  442.     Me->CustomsDutyRevenue += (int)(Me->PublicWorks * 100.0);
  443.     Me->CustomsDutyRevenue = (int)((float)Me->CustomsDuty / 100.0 *
  444.                      (float)Me->CustomsDutyRevenue);
  445.     
  446.     Me->SalesTaxRevenue = Me->Nobles * 50 + Me->Merchants * 25 +
  447.                      (int)(Me->PublicWorks * 10.0);
  448.     Me->SalesTaxRevenue *= (y * (5 - Me->Justice) * Me->SalesTax);
  449.     Me->SalesTaxRevenue /= 200;
  450.     
  451.     Me->IncomeTaxRevenue = Me->Nobles * 250 + (int)(Me->PublicWorks * 20.0);
  452.     Me->IncomeTaxRevenue += (10 * Me->Justice * Me->Nobles * y);
  453.     Me->IncomeTaxRevenue *= Me->IncomeTax;
  454.     Me->IncomeTaxRevenue /= 100;
  455.     
  456.     revenues = Me->CustomsDutyRevenue + Me->SalesTaxRevenue +
  457.         Me->IncomeTaxRevenue + Me->JusticeRevenue;
  458.     printf("State revenues %d gold florins.\n", revenues);
  459.     printf("Customs Duty\tSales Tax\tIncome Tax\tJustice\n");
  460.     printf("%d\t\t%d\t\t%d\t\t%d %s\n", Me->CustomsDutyRevenue,
  461.             Me->SalesTaxRevenue, Me->IncomeTaxRevenue,
  462.             Me->JusticeRevenue, string);
  463.     return;
  464. }
  465.  
  466. void ChangeTitle(player *Me)
  467. {
  468.     if(Me->MaleOrFemale == True)
  469.         strcpy(Me->Title, MaleTitles[Me->TitleNum]);
  470.     else
  471.         strcpy(Me->Title, FemaleTitles[Me->TitleNum]);
  472.     
  473.     if(Me->TitleNum == 7)
  474.     {
  475.         Me->IWon = True;
  476.         return;
  477.     }
  478.     
  479.     return;
  480. }
  481.  
  482. void NewLandAndGrainPrices(player *Me)
  483. {
  484.     float x, y, MyRandom;
  485.     int h;
  486.     
  487.     /* Generate an offset for use in later int->float conversions. */
  488.     MyRandom = (float)((float)rand() / (float)RAND_MAX);
  489.     
  490.     /* If you think this C code is ugly, you should see the original BASIC. */
  491.     x = (float)Me->Land;
  492.     y = (((float)Me->Serfs - (float)Me->Mills) * 100.0) * 5.0;
  493.     if(y < 0.0)
  494.         y = 0.0;
  495.     
  496.     if(y < x)
  497.         x = y;
  498.     
  499.     y = (float)Me->GrainReserve * 2.0;
  500.     if(y < x)
  501.         x = y;
  502.     
  503.     y = (float)Me->Harvest + (MyRandom - 0.5);
  504.     h = (int)(x * y);
  505.     Me->GrainReserve += h;
  506.     Me->GrainDemand = (Me->Nobles * 100) + (Me->Cathedral * 40) +
  507.                   (Me->Merchants * 30);
  508.     Me->GrainDemand += ((Me->Soldiers * 10) + (Me->Serfs * 5));
  509.     Me->LandPrice = (3.0 * (float)Me->Harvest + (float)Random(6) + 10.0) / 10.0;
  510.     
  511.     if(h < 0)
  512.     h *= -1;
  513.  
  514.     if(h < 1)
  515.         y = 2.0;
  516.     else
  517.     {
  518.         y = (float)((float)Me->GrainDemand / (float)h);
  519.         if(y > 2.0)
  520.             y = 2.0;
  521.     }
  522.     
  523.     if(y < 0.8)
  524.         y = 0.8;
  525.     
  526.     Me->LandPrice *= y;
  527.     if(Me->LandPrice < 1.0) Me->LandPrice = 1.0;
  528.     Me->GrainPrice = (int)(((6.0 - (float)Me->Harvest) * 3.0 + (float)Random(5)
  529.                 + (float)Random(5)) * 4.0 * y);
  530.     Me->RatsAte = h; 
  531.     return;
  532. }
  533.  
  534. void PrintGrain(player *Me)
  535. {
  536.     switch(Me->Harvest)
  537.     {
  538.     case 0: 
  539.         case 1: printf("Drought. Famine Threatens. "); break;
  540.         case 2: printf("Bad Weather. Poor Harvest. "); break;
  541.         case 3: printf("Normal Weather. Average Harvest. "); break;
  542.         case 4: printf("Good Weather. Fine Harvest. "); break;
  543.         case 5: printf("Excellent Weather. Great Harvest! "); break;
  544.     }
  545.     
  546.     return;
  547. }
  548.  
  549. int ReleaseGrain(player *Me)
  550. {
  551.     double xp, zp;
  552.     float x, z;
  553.     char string[256];
  554.     int HowMuch, Maximum, Minimum;
  555.     boolean IsOK;
  556.     
  557.     IsOK = False;
  558.     Minimum = Me->GrainReserve / 5;
  559.     Maximum = (Me->GrainReserve - Minimum);
  560.     while(IsOK == False)
  561.     {
  562.         printf("How much grain will you release for consumption?\n");
  563.         printf("1 = Minimum (%d), 2 = Maximum(%d), or enter a value: ",
  564.             Minimum, Maximum);
  565.         fgets(string, 255, stdin);
  566.         HowMuch = (int)atoi(string);
  567.  
  568.         if(HowMuch == 1)
  569.         HowMuch = Minimum;
  570.     if(HowMuch == 2)
  571.         HowMuch = Maximum;
  572.  
  573.         /* Are we being a Scrooge? */
  574.     if(HowMuch < Minimum)
  575.             printf("You must release at least 20%% of your reserves.\n");
  576.     
  577.         /* Whoa. Slow down there son. */
  578.     else if(HowMuch > Maximum)
  579.             printf("You must keep at least 20%%.\n");
  580.     else
  581.         IsOK = True;
  582.     }
  583.     
  584.     Me->SoldierPay = Me->MarketRevenue = Me->NewSerfs = Me->DeadSerfs = 0;
  585.     Me->TransplantedSerfs = Me->FleeingSerfs = 0;
  586.     Me->InvadeMe = False;
  587.     
  588.     Me->GrainReserve -= HowMuch;
  589.     z = (float)HowMuch / (float)Me->GrainDemand - 1.0;
  590.     if(z > 0.0)
  591.         z /= 2.0;
  592.     if(z > 0.25)
  593.         z = z / 10.0 + 0.25;
  594.     
  595.     zp = 50.0 - (double)Me->CustomsDuty - (double)Me->SalesTax -
  596.             (double)Me->IncomeTax;
  597.     if(zp < 0.0)
  598.         zp *= (double)Me->Justice;
  599.     zp /= 10.0;
  600.     if(zp > 0.0)
  601.         zp += (3.0 - (double)Me->Justice);
  602.     
  603.     z += ((float)zp / 10.0);
  604.     if(z > 0.5)
  605.         z = 0.5;
  606.     
  607.     if(HowMuch < (Me->GrainDemand - 1))
  608.     {
  609.         x = ((float)Me->GrainDemand - (float)HowMuch) /
  610.         (float)Me->GrainDemand * 100.0 - 9.0;
  611.         xp = (double)x;
  612.         if(x > 65.0)
  613.             x = 65.0;
  614.         if(x < 0.0)
  615.         {
  616.             xp = 0.0;
  617.             x = 0.0;
  618.         }
  619.         SerfsProcreating(Me, 3.0);
  620.         SerfsDecomposing(Me, xp + 8.0);
  621.     }
  622.     else
  623.     {
  624.         SerfsProcreating(Me, 7.0);
  625.         SerfsDecomposing(Me, 3.0);
  626.         if((Me->CustomsDuty + Me->SalesTax) < 35)
  627.             Me->Merchants += Random(4);
  628.         if(Me->IncomeTax < Random(28))
  629.         {
  630.             Me->Nobles += Random(2);
  631.             Me->Clergy += Random(3);
  632.         }
  633.         if(HowMuch > (int)((float)Me->GrainDemand * 1.3))
  634.         {
  635.             zp = (double)Me->Serfs / 1000.0;
  636.             z = ((float)HowMuch - (float)(Me->GrainDemand)) /
  637.                 (float)Me->GrainDemand * 10.0;
  638.             z *= ((float)zp * (float)Random(25));
  639.             z += (float)Random(40);
  640.         Me->TransplantedSerfs = (int)z;
  641.         Me->Serfs += Me->TransplantedSerfs;
  642.         printf("%d serfs move to the city\n", Me->TransplantedSerfs);
  643.             zp = (double)z;
  644.             z = ((float)zp * (float)rand()) / (float)RAND_MAX;
  645.             if(z > 50.0)
  646.                 z = 50.0;
  647.             Me->Merchants += (int)z;
  648.             Me->Nobles++;
  649.             Me->Clergy += 2;
  650.         }
  651.     }
  652.     
  653.     if(Me->Justice > 2)
  654.     {
  655.         Me->JusticeRevenue = Me->Serfs / 100 * (Me->Justice - 2) *
  656.                          (Me->Justice - 2);
  657.         Me->JusticeRevenue = Random(Me->JusticeRevenue);
  658.         Me->Serfs -= Me->JusticeRevenue;
  659.         Me->FleeingSerfs = Me->JusticeRevenue;
  660.     printf("%d serfs flee harsh justice\n", Me->FleeingSerfs);
  661.     }
  662.     
  663.     Me->MarketRevenue = Me->Marketplaces * 75;
  664.     if(Me->MarketRevenue > 0)
  665.     {
  666.         Me->Treasury += Me->MarketRevenue;
  667.     printf("Your market earned %d florins.\n", Me->MarketRevenue);
  668.     }
  669.     
  670.     Me->MillRevenue = Me->Mills * (55 + Random(250));
  671.     if(Me->MillRevenue > 0)
  672.     {
  673.         Me->Treasury += Me->MillRevenue;
  674.     printf("Your woolen mill earned %d florins.\n", Me->MillRevenue);
  675.     }
  676.     
  677.     Me->SoldierPay = Me->Soldiers * 3;
  678.     Me->Treasury -= Me->SoldierPay;
  679.     printf("You paid your soldiers %d florins.\n", Me->SoldierPay);
  680.     printf("You have %d serfs in your city.\n", Me->Serfs);
  681.     printf("(Press ENTER): ");
  682.     fgets(string, 255, stdin);
  683.     
  684.     if((Me->Land / 1000) > Me->Soldiers)
  685.     {
  686.         Me->InvadeMe = True;
  687.         return(3);
  688.     }
  689.     if((Me->Land / 500) > Me->Soldiers)
  690.     {
  691.         Me->InvadeMe = True;
  692.         return(3);
  693.     }
  694.     
  695.     return(0);
  696. }
  697.  
  698. void SeizeAssets(player *Me)
  699. {
  700.     char string[256];
  701.  
  702.     Me->Marketplaces = 0;
  703.     Me->Palace = 0;
  704.     Me->Cathedral = 0;
  705.     Me->Mills = 0;
  706.     Me->Land = 6000;
  707.     Me->PublicWorks = 1.0;
  708.     Me->Treasury = 100;
  709.     Me->IsBankrupt = False;
  710.  
  711.     printf("\n\n%s %s is bankrupt.\n", Me->Title, Me->Name);
  712.     printf("\nCreditors have seized much of your assets.\n");
  713.     printf("\n(Press ENTER): ");
  714.     fgets(string, 255, stdin);
  715.     
  716.     return;
  717. }
  718.  
  719. void SellGrain(player *Me)
  720. {
  721.     char string[256];
  722.     int HowMuch;
  723.  
  724.     printf("How much grain do you want to sell? ");
  725.     fgets(string, 255, stdin);
  726.     HowMuch = (int)atoi(string);
  727.  
  728.     if(HowMuch > Me->GrainReserve)
  729.     {
  730.     printf("You don't have it.\n");
  731.         return;
  732.     }    
  733.     
  734.     Me->Treasury += (HowMuch * Me->GrainPrice / 1000);
  735.     Me->GrainReserve -= HowMuch;
  736.     return;
  737. }
  738.  
  739. void SellLand(player *Me)
  740. {
  741.     char string[256];
  742.     int HowMuch;
  743.  
  744.     printf("How much land do you want to sell? ");
  745.     fgets(string, 255, stdin);
  746.     HowMuch = (int)atoi(string);
  747.  
  748.     if(HowMuch > (Me->Land - 5000))
  749.     {
  750.     printf("You can't sell that much\n");
  751.         return;    
  752.     }
  753.     
  754.     Me->Land -= HowMuch;
  755.     Me->Treasury += (int)(((float)HowMuch * Me->LandPrice));
  756.     return;
  757. }
  758.  
  759. void SerfsDecomposing(player *Me, float MyScale)
  760. {
  761.     int absc;
  762.     float ord;
  763.     
  764.     absc = (int)MyScale;
  765.     ord = MyScale - (float)absc;
  766.     
  767.     Me->DeadSerfs = (int)((((float)Random(absc) + ord) * (float)Me->Serfs) /
  768.             100.0);
  769.     Me->Serfs -= Me->DeadSerfs;
  770.     printf("%d serfs die this year.\n", Me->DeadSerfs);
  771.     
  772.     return;
  773. }
  774.  
  775. void SerfsProcreating(player *Me, float MyScale)
  776. {
  777.     int absc;
  778.     float ord;
  779.     
  780.     absc = (int)MyScale;
  781.     ord = MyScale - (float)absc;
  782.     
  783.     Me->NewSerfs = (int)((((float)Random(absc) + ord) * (float)Me->Serfs) /
  784.            100.0);
  785.     Me->Serfs += Me->NewSerfs;
  786.     printf("%d serfs born this year.\n", Me->NewSerfs);
  787.     
  788.     return;
  789. }
  790.  
  791. void PrintInstructions(void)
  792. {
  793.     char string[256];
  794.     
  795.     printf("Santa Paravia and Fiumaccio\n\n");
  796.     printf("You are the ruler of a 15th century Italian city state.\n");
  797.     printf("If you rule well, you will receive higher titles. The\n");
  798.     printf("first player to become king or queen wins. Life expectancy\n");
  799.     printf("then was brief, so you may not live long enough to win.\n");
  800.     printf("The computer will draw a map of your state. The size\n");
  801.     printf("of the area in the wall grows as you buy more land. The\n");
  802.     printf("size of the guard tower in the upper left corner shows\n");
  803.     printf("the adequacy of your defenses. If it shrinks, equip more\n");
  804.     printf("soldiers! If the horse and plowman is touching the top of the wall,\n");
  805.     printf("all your land is in production. Otherwise you need more\n");
  806.     printf("serfs, who will migrate to your state if you distribute\n");
  807.     printf("more grain than the minimum demand. If you distribute less\n");
  808.     printf("grain, some of your people will starve, and you will have\n");
  809.     printf("a high death rate. High taxes raise money, but slow down\n");
  810.     printf("economic growth. (Press ENTER to begin game)\n");
  811.     fgets(string, 255, stdin);
  812.  
  813.     return;
  814. }
  815.  
  816. void PlayGame(player MyPlayers[6], int NumOfPlayers)
  817. {
  818.     boolean AllDead, Winner;
  819.     int i, WinningPlayer = 0;
  820.     player Baron;
  821.  
  822.     AllDead = False;
  823.     Winner = False;
  824.  
  825.     InitializePlayer(&Baron, 1400, 6, 4, "Peppone", True);
  826.  
  827.     while(AllDead == False && Winner == False)
  828.     {
  829.         for(i = 0; i < NumOfPlayers; i++)
  830.             if(MyPlayers[i].IsDead == False)
  831.                 NewTurn(&MyPlayers[i], NumOfPlayers, MyPlayers,
  832.                                &Baron); 
  833.  
  834.         AllDead = True;
  835.         for(i = 0; i < NumOfPlayers; i++)
  836.             if(AllDead == True && MyPlayers[i].IsDead == False)
  837.                 AllDead = False;
  838.  
  839.         for(i = 0; i < NumOfPlayers; i++)
  840.             if(MyPlayers[i].IWon == True)
  841.             {
  842.                 Winner = True;
  843.                 WinningPlayer = i;
  844.             }
  845.     }
  846.  
  847.     if(AllDead == True)
  848.     {
  849.         printf("The game has ended.\n");
  850.         return;
  851.     }
  852.  
  853.     printf("Game Over. %s %s wins.\n", MyPlayers[WinningPlayer].Title,
  854.                MyPlayers[WinningPlayer].Name);
  855.     return;
  856. }
  857.  
  858. void NewTurn(player *Me, int HowMany, player MyPlayers[6], player *Baron)
  859. {
  860.     int i;
  861.  
  862.     GenerateHarvest(Me);
  863.     NewLandAndGrainPrices(Me);
  864.     BuySellGrain(Me);
  865.     ReleaseGrain(Me);
  866.     if(Me->InvadeMe == True)
  867.     {
  868.         for(i = 0; i < HowMany; i++)
  869.             if(i != Me->WhichPlayer)
  870.                 if(MyPlayers[i].Soldiers > (Me->Soldiers * 2.4))
  871.                 {
  872.                     AttackNeighbor(&MyPlayers[i], Me);
  873.                     i = 9;
  874.                 }
  875.         if(i != 9)
  876.             AttackNeighbor(Baron, Me);
  877.     }
  878.     AdjustTax(Me);
  879.     DrawMap(Me);
  880.     StatePurchases(Me, HowMany, MyPlayers);
  881.     CheckNewTitle(Me);
  882.     
  883.     Me->Year++;
  884.     if(Me->Year == Me->YearOfDeath)
  885.         ImDead(Me);
  886.     if(Me->TitleNum >= 7)
  887.         Me->IWon = True;
  888. }
  889.  
  890. void BuySellGrain(player *Me)
  891. {
  892.     boolean Finished;
  893.     char string[256];
  894.  
  895.     Finished = False;
  896.     while(Finished == False)
  897.     {
  898.         printf("\nYear %d\n", Me->Year);
  899.         printf("\n%s %s\n\n", Me->Title, Me->Name);
  900.         printf("Rats ate %d%% of your grain reserves.\n", Me->Rats);
  901.         PrintGrain(Me);
  902.         printf("(%d steres)\n\n", Me->RatsAte);
  903.         printf("Grain\tGrain\tPrice of\tPrice of\tTreasury\n");
  904.         printf("Reserve\tDemand\tGrain\t\tLand\n");
  905.         printf("%d\t%d\t%d\t\t%.2f\t\t%d\n", Me->GrainReserve,
  906.             Me->GrainDemand, Me->GrainPrice, Me->LandPrice,
  907.             Me->Treasury);
  908.         printf("steres\tsteres\t1000 st.\thectare\t\tgold florins\n");
  909.         printf("\nYou have %d hectares of land.\n", Me->Land);
  910.         printf("\n1. Buy grain, 2. Sell grain, 3. Buy land,");
  911.         printf(" 4. Sell land\n(Enter q to continue): ");
  912.         fgets(string, 255, stdin);
  913.  
  914.         if(string[0] == 'q')
  915.             Finished = True;
  916.         if(string[0] == '1')
  917.             BuyGrain(Me);
  918.         if(string[0] == '2')
  919.             SellGrain(Me);
  920.         if(string[0] == '3')
  921.             BuyLand(Me);
  922.         if(string[0] == '4')
  923.             SellLand(Me);
  924.     }
  925.  
  926.     return;
  927. }
  928.  
  929. void AdjustTax(player *Me)
  930. {
  931.     char string[256];
  932.     int val = 1, duty = 0;
  933.  
  934.     string[0] = '\0';
  935.     while(val != 0 || string[0] != 'q')
  936.     {
  937.         printf("\n%s %s\n\n", Me->Title, Me->Name);
  938.                 GenerateIncome(Me);
  939.         printf("(%d%%)\t\t(%d%%)\t\t(%d%%)",
  940.                 Me->CustomsDuty, Me->SalesTax,
  941.                 Me->IncomeTax);
  942.             printf("\n1. Customs Duty, 2. Sales Tax, 3. Wealth Tax, ");
  943.         printf("4. Justice\n");
  944.         printf("Enter tax number for changes, q to continue: ");
  945.         fgets(string, 255, stdin);
  946.         val = (int)atoi(string);
  947.  
  948.         switch(val)
  949.         {
  950.             case 1: printf("New customs duty (0 to 100): ");
  951.                 fgets(string, 255, stdin);
  952.                 duty = (int)atoi(string);
  953.                 if(duty > 100) duty = 100;
  954.                 if(duty < 0) duty = 0;
  955.                 Me->CustomsDuty = duty;
  956.                 break;
  957.             case 2: printf("New sales tax (0 to 50): ");
  958.                 fgets(string, 255, stdin);
  959.                 duty = (int)atoi(string);
  960.                 if(duty > 50) duty = 50;
  961.                 if(duty < 0) duty = 0;
  962.                 Me->SalesTax = duty;
  963.                 break;
  964.             case 3: printf("New wealth tax (0 to 25): ");
  965.                 fgets(string, 255, stdin);
  966.                 duty = (int)atoi(string);
  967.                 if(duty > 25) duty = 25;
  968.                 if(duty < 0) duty = 0;
  969.                 Me->IncomeTax = duty;
  970.                 break;
  971.             case 4: printf("Justice: 1. Very fair, 2. Moderate");
  972.                 printf(" 3. Harsh, 4. Outrageous: ");
  973.                 fgets(string, 255, stdin);
  974.                 duty = (int)atoi(string);
  975.                 if(duty > 4) duty = 4;
  976.                 if(duty < 1) duty = 1;
  977.                 Me->Justice = duty;
  978.                 break;
  979.         }
  980.     
  981.     }
  982.     AddRevenue(Me);
  983.     if(Me->IsBankrupt == True)
  984.         SeizeAssets(Me);
  985. }    
  986.  
  987. void DrawMap(player *Me)
  988. {
  989.     /* Not implemented yet. */
  990.     return;
  991. }
  992.  
  993. void StatePurchases(player *Me, int HowMany, player MyPlayers[6])
  994. {
  995.     char string[256];
  996.     int val = 1;
  997.  
  998.     string[0] = '\0';
  999.     while(val != 0 || string[0] != 'q')
  1000.     {
  1001.             printf("\n\n%s %s\nState purchases.\n", Me->Title, Me->Name);
  1002.         printf("\n1. Marketplace (%d)\t\t\t\t1000 florins\n",
  1003.                 Me->Marketplaces);
  1004.         printf("2. Woolen mill (%d)\t\t\t\t2000 florins\n",
  1005.                 Me->Mills);
  1006.         printf("3. Palace (partial) (%d)\t\t\t\t3000 florins\n",
  1007.                 Me->Palace);
  1008.         printf("4. Cathedral (partial) (%d)\t\t\t5000 florins\n",
  1009.                 Me->Cathedral);
  1010.             printf("5. Equip one platoon of serfs as soldiers\t500 florins\n");
  1011.         printf("\nYou have %d gold florins.\n", Me->Treasury);
  1012.         printf("\nTo continue, enter q. To compare standings, enter 6\n");
  1013.         printf("Your choice: ");
  1014.         fgets(string, 255, stdin);
  1015.         val = (int)atoi(string);
  1016.  
  1017.         switch(val)
  1018.         {
  1019.             case 1: BuyMarket(Me); break;
  1020.             case 2: BuyMill(Me); break;
  1021.             case 3: BuyPalace(Me); break;
  1022.             case 4: BuyCathedral(Me); break;
  1023.             case 5: BuySoldiers(Me); break;
  1024.             case 6: ShowStats(MyPlayers, HowMany);
  1025.         }
  1026.     }
  1027.     return;
  1028. }
  1029.  
  1030. void ShowStats(player MyPlayers[6], int HowMany)
  1031. {
  1032.     int i = 0;
  1033.     char string[256];
  1034.  
  1035.     printf("Nobles\tSoldiers\tClergy\tMerchants\tSerfs\tLand\tTreasury\n");
  1036.     for(; i < HowMany; i++)
  1037.         printf("\n%s %s\n%d\t%d\t\t%d\t%d\t\t%d\t%d\t%d\n",
  1038.                 MyPlayers[i].Title, MyPlayers[i].Name,
  1039.                 MyPlayers[i].Nobles, MyPlayers[i].Soldiers,
  1040.                 MyPlayers[i].Clergy, MyPlayers[i].Merchants,
  1041.                 MyPlayers[i].Serfs, MyPlayers[i].Land,
  1042.                 MyPlayers[i].Treasury);
  1043.  
  1044.     printf("\n(Press ENTER): ");
  1045.     fgets(string, 255, stdin);
  1046.  
  1047.     return;
  1048. }
  1049.  
  1050. void ImDead(player *Me)
  1051. {
  1052.     char string[256];
  1053.     int why;
  1054.     
  1055.     printf("\n\nVery sad news.\n%s %s has just died\n", Me->Title,
  1056.             Me->Name);
  1057.     
  1058.     if(Me->Year > 1450)
  1059.         printf("of old age after a long reign.\n");
  1060.     else
  1061.     {
  1062.         why = Random(8);
  1063.         switch(why)
  1064.         {
  1065.             case 0:
  1066.             case 1:
  1067.             case 2:
  1068.             case 3: printf("of pneumonia after a cold winter in a drafty castle.\n"); break;
  1069.             case 4: printf("of typhoid after drinking contaminated water.\n"); break;
  1070.             case 5: printf("in a smallpox epidemic.\n"); break;
  1071.             case 6: printf("after being attacked by robbers while travelling.\n"); break;
  1072.             case 7:
  1073.             case 8: printf("of food poisoning.\n"); break;
  1074.         }
  1075.     }
  1076.  
  1077.     Me->IsDead = True;
  1078.     printf("\n(Press ENTER): ");
  1079.     fgets(string, 255, stdin);
  1080.     return;
  1081. }
  1082.